//--------------------------------------------------- // Purpose: Implement simple version of minesweeper. // Author: John Gauch //--------------------------------------------------- #include #include #include using namespace std; const int SIZE = 10; const int MINE = 9; bool mine[SIZE][SIZE]; //------------------------------------------------------------ // Initialize the known and count arrays //------------------------------------------------------------ void Init( bool known[SIZE][SIZE], int count[SIZE][SIZE] ) { // Loop over known array for (int row = 0; row < SIZE; row++) for (int col = 0; col < SIZE; col++) known[row][col] = false; // Loop over count array for (int row = 0; row < SIZE; row++) for (int col = 0; col < SIZE; col++) count[row][col] = 0; // Place some random mines for (int num = 0; num < SIZE; num++) { int row = random() % SIZE; int col = random() % SIZE; count[row][col] = MINE; } // Loop over count array for (int row = 0; row < SIZE; row++) for (int col = 0; col < SIZE; col++) if (count[row][col] != MINE) { // Count mines in 3x3 region int bombs = 0; for (int r = row-1; r <= row+1; r++) for (int c = col-1; c <= col+1; c++) if ((0 <= r) && (r < SIZE) && (0 <= c) && (c < SIZE) && (count[r][c] == MINE)) bombs++; count[row][col] = bombs; } } //------------------------------------------------------------ // Display the known and count arrays //------------------------------------------------------------ void Display( bool known[SIZE][SIZE], int count[SIZE][SIZE] ) { cout << " "; for (int col = 0; col < SIZE; col++) cout << setfill(' ') << setw(4) << col; cout << endl; for (int row = 0; row < SIZE; row++) { cout << " "; for (int col = 0; col < SIZE; col++) cout << "+---"; cout << "+\n" << setw(2) << row << " "; for (int col = 0; col < SIZE; col++) if (mine[row][col]) cout << "| + "; else if (!known[row][col]) cout << "| . "; else if (count[row][col] == 0) cout << "| "; else if (count[row][col] == MINE) cout << "| * "; else cout << "| " << count[row][col] << " "; cout << "|\n"; } cout << " "; for (int col = 0; col < SIZE; col++) cout << "+---"; cout << "+\n"; } //------------------------------------------------------------ // Check if player wins //------------------------------------------------------------ bool CheckWin(bool known[SIZE][SIZE], int count[SIZE][SIZE]) { // Check board for (int row = 0; row < SIZE; row++) for (int col = 0; col < SIZE; col++) if (!known[row][col] && count[row][col] != MINE) return false; return true; } //------------------------------------------------------------ // Check if player loses //------------------------------------------------------------ bool CheckLose(int count[SIZE][SIZE], int row, int col) { // Check board return (count[row][col] == MINE); } //------------------------------------------------------------ // Get move from player //------------------------------------------------------------ void GetUserMove(int &row, int &col) { // Prompt for move row = col = -1; while ((row < 0) || (row >= SIZE) || (col < 0) || (col >= SIZE)) { cout << "Enter row col: "; cin >> row >> col; } } //------------------------------------------------------------ // Make move and clear board //------------------------------------------------------------ void Play(bool known[SIZE][SIZE], int count[SIZE][SIZE], int row, int col) { // Make move known[row][col] = true; if (count[row][col] == 0) { // Clear board for (int r = row-1; r <= row+1; r++) for (int c = col-1; c <= col+1; c++) if ((0 <= r) && (r < SIZE) && (0 <= c) && (c < SIZE) && (!known[r][c]) && (count[r][c] != MINE)) Play(known, count, r, c); } } //------------------------------------------------------------ // Select a random location //------------------------------------------------------------ void GetRandom( bool known[SIZE][SIZE], int & row, int & col ) { // Select random unknown location row = random() % SIZE; col = random() % SIZE; while (known[row][col] || mine[row][col]) { row = random() % SIZE; col = random() % SIZE; } cout << "Random Play: " << row << " " << col << endl; } //------------------------------------------------------------ // Play on all safe locations based on displayed counts //------------------------------------------------------------ void PlaySafe( bool known[SIZE][SIZE], int count[SIZE][SIZE] ) { // Loop calculating safe moves bool done = false; while (!done) { // Initialize mine map for (int row = 0; row < SIZE; row++) for (int col = 0; col < SIZE; col++) mine[row][col] = false; // Initialize safe map bool safe[SIZE][SIZE]; for (int row = 0; row < SIZE; row++) for (int col = 0; col < SIZE; col++) safe[row][col] = false; // Search for known count of >=1 for (int row = 0; row < SIZE; row++) for (int col = 0; col < SIZE; col++) if (known[row][col] && count[row][col] >= 1) { // Check 3x3 neighborhood for unknown locations int unknown_count = 0; for (int r = row-1; r <= row+1; r++) for (int c = col-1; c <= col+1; c++) if ((0 <= r) && (r < SIZE) && (0 <= c) && (c < SIZE) && (!known[r][c])) unknown_count++; // Save mine location if (unknown_count == count[row][col]) for (int r = row-1; r <= row+1; r++) for (int c = col-1; c <= col+1; c++) if ((0 <= r) && (r < SIZE) && (0 <= c) && (c < SIZE) && (!known[r][c])) mine[r][c] = true; } // Search for known count of >=1 for (int row = 0; row < SIZE; row++) for (int col = 0; col < SIZE; col++) if (known[row][col] && count[row][col] >= 1) { // Check 3x3 neighborhood for unknown locations int mine_count = 0; int unknown_count = 0; for (int r = row-1; r <= row+1; r++) for (int c = col-1; c <= col+1; c++) if ((0 <= r) && (r < SIZE) && (0 <= c) && (c < SIZE) && (!known[r][c])) { unknown_count++; if (mine[r][c]) mine_count++; } // Mark safe location if ((unknown_count > mine_count) && (mine_count == count[row][col])) for (int r = row-1; r <= row+1; r++) for (int c = col-1; c <= col+1; c++) if ((0 <= r) && (r < SIZE) && (0 <= c) && (c < SIZE) && (!known[r][c]) && !mine[r][c]) safe[r][c] = true; } // Make safe moves done = true; for (int row = 0; row < SIZE; row++) for (int col = 0; col < SIZE; col++) if (safe[row][col]) { cout << "AI Play: " << row << " " << col << endl; Play(known, count, row, col); done = false; } } } //------------------------------------------------------------ // Main program //------------------------------------------------------------ int main(int argc, char *argv[]) { // Enable AI bool ai = (argc == 2) && (argv[1][0] == 'a'); if (ai) cout << "AI is enabled\n"; // Initialize game int row, col; bool known[SIZE][SIZE]; int count[SIZE][SIZE]; srandom(time(NULL)); Init(known, count); // Loop playing game bool win = false; bool lose = false; while (!win && !lose) { if (ai) { GetRandom(known, row, col); Play(known, count, row, col); if (!CheckLose(count, row, col)) PlaySafe(known, count); } else { Display(known, count); GetUserMove(row, col); Play(known, count, row, col); } win = CheckWin(known, count); lose = CheckLose(count, row, col); } // Display final board Display(known, count); if (win) cout << "Congratulations, you win.\n\n"; else cout << "Sorry, you lose.\n\n"; }